import { areHookInputsEqual, HookLayout, HookPassive } from "./utils"
import { scheduleUpdateOnFiber } from "./workLoop"

let currentlyRenderingFiber = null
let workInProgressHook = null
let currentHook = null

export function renderHooks(wip) {
  currentlyRenderingFiber = wip
  currentlyRenderingFiber.memorizedState = null
  currentlyRenderingFiber.updateQueueOfEffect = []
  currentlyRenderingFiber.updateQueueOfLayoutEffect = []
  workInProgressHook = null
}

function updateWorkInProgressHook() {
  const current = currentlyRenderingFiber.alternate
  let hook
  if(current) {
    // 是更新阶段  老的基础上做更新
    currentlyRenderingFiber.memorizedState = current.memorizedState
    if(workInProgressHook) {
      hook = workInProgressHook = workInProgressHook.next
      currentHook = currentHook.next
    }else{
      hook = workInProgressHook = current.memorizedState
      currentHook = current.memorizedState;
    }
  }else{
    // 初次渲染
    currentHook = null
    hook = {
      memorizedState: null,
      next: null
    }
    // 是否是头节点
    if(workInProgressHook) {
      workInProgressHook = workInProgressHook.next = hook
    }else{
      workInProgressHook = currentlyRenderingFiber.memorizedState = hook
    }
  }
  return hook
}

export function useReducer(reducer, initalState) {

  const hook = updateWorkInProgressHook()

  if(!currentlyRenderingFiber.alternate) {
    hook.memorizedState = initalState
  }
  const dispatch = (action) => {
    // 修改状态值 更新组件
    hook.memorizedState =  reducer ? reducer(hook.memorizedState, action) : action
    scheduleUpdateOnFiber(currentlyRenderingFiber)
  }
  return [hook.memorizedState, dispatch]
}

export function useState(initalState) {
  return useReducer(null, initalState)
}

function updateEffectImpl(hookFlags, create, deps) {
  const hook = updateWorkInProgressHook()

  if(currentHook) {
    // 检查deps是否发生变化
    const prevEffect = currentHook.memorizedState
    if(deps) {
      const prevDeps = prevEffect.deps
      if(areHookInputsEqual(deps, prevDeps)) {
        return
      }
    }
  }

  const effect = {hookFlags, create, deps}
  hook.memorizedState = effect

  if(hookFlags & HookPassive) {
    currentlyRenderingFiber.updateQueueOfEffect.push(effect)
  }else if(hookFlags & HookLayout){
    currentlyRenderingFiber.updateQueueOfLayoutEffect.push(effect)
  }
}

export function useEffect(create, deps) {
  return updateEffectImpl(HookPassive, create, deps)
}

export function useLayoutEffect(create, deps) {
  return updateEffectImpl(HookLayout, create, deps)
}